#!/usr/bin/env python3
"""
GitLab平台界面模块
包含GitLab平台的所有界面逻辑和数据处理功能
"""

import os
import random
from typing import List, Dict, Tuple

import pandas as pd
import plotly.express as px
import streamlit as st
from loguru import logger

from .commits_analyzer import GitLabCommitsAnalyzer
from .repos_fetcher import GitLabReposFetcher


class GitLabInterface:
    """GitLab平台界面管理类"""

    def __init__(self):
        self.platform_name = "GitLab"
        # 预定义的GitLab实例 - 从环境变量读取token
        self.gitlab_instances = {
            "研发中心git": {
                "url": "http://gitlab.waterism.com:8888",
                "token": os.getenv('GITLAB_ACCESS_TOKEN', 'fQxdTgp-A2ytx6eoUtX3')
            },
            "研发中心软件开发部": {
                "url": "http://10.10.50.201/",
                "token": os.getenv('GITLAB_ACCESS_TOKEN', 'EJAoCB5GWTaLYrhspXhC')
            },
            "自定义": {
                "url": "",
                "token": ""
            }
        }

    def get_random_token(self) -> str:
        """从环境变量中获取随机GitLab访问令牌"""
        token_str = os.getenv('GITLAB_ACCESS_TOKEN', '')
        if not token_str:
            return ''
        tokens = [token.strip() for token in token_str.split(',') if token.strip()]
        if not tokens:
            return ''
        return random.choice(tokens)

    def render_sidebar_config(self) -> Tuple[str, str, str]:
        """渲染GitLab侧边栏配置
        
        Returns:
            Tuple[access_token, gitlab_url, group_id]: 访问令牌、GitLab URL和群组ID
        """
        st.sidebar.subheader("🔧 GitLab 配置")

        # GitLab实例选择
        selected_instance = st.sidebar.selectbox(
            "选择GitLab实例",
            list(self.gitlab_instances.keys()),
            index=0,
            help="选择要连接的GitLab服务器实例",
            key="platforms_gitlab_instance_select"
        )

        # 根据选择的实例设置默认值
        default_url = self.gitlab_instances[selected_instance]["url"]
        default_token = self.gitlab_instances[selected_instance]["token"]

        # 如果选择了自定义，则从环境变量获取
        if selected_instance == "自定义":
            env_gitlab_token = self.get_random_token()
            env_gitlab_url = os.getenv('GITLAB_URL', 'http://gitlab.waterism.com:8888')
            default_url = env_gitlab_url
            default_token = env_gitlab_token

        # 显示当前选择的实例信息
        if selected_instance != "自定义":
            st.sidebar.success(f"✅ 已选择 {selected_instance}")
            st.sidebar.info(f"🔗 服务器: {default_url}")
        else:
            st.sidebar.info("ℹ️ 请手动配置GitLab连接信息")

        access_token = st.sidebar.text_input(
            "GitLab Access Token",
            value=default_token,
            type="password",
            help="GitLab API访问令牌",
            key="platforms_gitlab_access_token"
        )

        gitlab_url = st.sidebar.text_input(
            "GitLab URL",
            value=default_url,
            help="GitLab服务器地址",
            key="platforms_gitlab_url"
        )

        # 群组ID默认为空，获取所有可访问项目
        group_id = ""  # 默认为空，获取所有可访问项目

        return access_token, gitlab_url, group_id

    def fetch_repositories(self, access_token: str, gitlab_url: str, group_id: str = "") -> pd.DataFrame:
        """获取GitLab仓库列表"""
        try:
            fetcher = GitLabReposFetcher(access_token, gitlab_url)
            with st.spinner(f"正在获取GitLab项目列表..."):
                if group_id:  # 如果指定了群组
                    df = fetcher.get_group_projects_dataframe(group_id)
                else:  # 获取所有可访问项目
                    df = fetcher.get_all_projects_dataframe()
            return df
        except Exception as e:
            st.error(f"获取GitLab仓库列表失败: {str(e)}")
            logger.error(f"获取GitLab仓库列表失败: {e}")
            return pd.DataFrame()

    def fetch_commits(self, access_token: str, gitlab_url: str, project_id: str,
                      since_date: str = None) -> pd.DataFrame:
        """获取GitLab提交记录"""
        try:
            analyzer = GitLabCommitsAnalyzer(access_token, gitlab_url)
            with st.spinner(f"正在获取GitLab项目 '{project_id}' 的提交记录..."):
                kwargs = {}
                if since_date:
                    kwargs['since'] = since_date
                commits = analyzer.get_project_commits(project_id, **kwargs)
                df = analyzer.commits_to_dataframe(commits)
            return df
        except Exception as e:
            st.error(f"获取GitLab提交记录失败: {str(e)}")
            logger.error(f"获取GitLab提交记录失败: {e}")
            return pd.DataFrame()

    def fetch_overall_analysis(self, access_token: str, gitlab_url: str, repos_df: pd.DataFrame, since_date: str) -> \
            List[pd.DataFrame]:
        """获取GitLab所有仓库的整体分析数据"""
        try:
            analyzer = GitLabCommitsAnalyzer(access_token, gitlab_url)
            overall_data = []

            progress_bar = st.progress(0)
            status_text = st.empty()
            total_repos = len(repos_df)

            for idx, repo in repos_df.iterrows():
                repo_name = repo['name']
                project_id = repo['id']
                status_text.text(f"正在分析GitLab项目: {repo_name} ({idx + 1}/{total_repos})")

                try:
                    kwargs = {}
                    if since_date:
                        kwargs['since'] = since_date

                    commits = analyzer.get_project_commits(project_id, **kwargs)
                    if commits:
                        df = analyzer.commits_to_dataframe(commits)
                        if not df.empty:
                            df['repo_name'] = repo_name
                            overall_data.append(df)

                except Exception as e:
                    logger.error(f"分析GitLab项目 {repo_name} 失败: {e}")
                    continue

                progress_bar.progress((idx + 1) / total_repos)

            progress_bar.empty()
            status_text.empty()
            return overall_data

        except Exception as e:
            st.error(f"GitLab整体分析失败: {str(e)}")
            logger.error(f"GitLab整体分析失败: {e}")
            return []

    def fetch_student_analysis(self, access_token: str, gitlab_url: str, repos_df: pd.DataFrame, since_date: str,
                               progress_callback=None) -> \
            List[Dict]:
        """获取GitLab提交者级别的详细分析数据"""
        try:
            analyzer = GitLabCommitsAnalyzer(access_token, gitlab_url)
            project_ids = repos_df['id'].tolist()

            # UI显示逻辑已移至UI层处理

            kwargs = {}
            if since_date:
                kwargs['since'] = since_date

            student_stats = analyzer.get_student_level_statistics_by_projects(
                project_ids, progress_callback=progress_callback, **kwargs
            )

            return student_stats

        except Exception as e:
            logger.error(f"GitLab提交者分析失败: {e}")
            raise e

    def display_repo_overview(self, df: pd.DataFrame):
        """显示GitLab仓库概览"""
        if df.empty:
            st.warning("没有GitLab仓库数据可显示")
            return

        st.subheader("📊 GitLab仓库概览")

        # 统计指标
        col1, col2, col3, col4 = st.columns(4)

        with col1:
            st.metric("总项目数", len(df))

        with col2:
            # GitLab使用visibility字段，private对应'private'
            private_count = len(df[df['visibility'] == 'private']) if 'visibility' in df.columns else 0
            st.metric("私有项目", private_count)

        with col3:
            fork_count = df['forked_from_project'].notna().sum() if 'forked_from_project' in df.columns else 0
            st.metric("Fork项目", fork_count)

        with col4:
            total_stars = df['star_count'].sum() if 'star_count' in df.columns else 0
            st.metric("总Star数", total_stars)

        # 可见性分布
        if 'visibility' in df.columns:
            st.subheader("🔒 项目可见性分布")
            visibility_counts = df['visibility'].value_counts()

            if not visibility_counts.empty:
                fig = px.pie(
                    values=visibility_counts.values,
                    names=visibility_counts.index,
                    title="项目可见性分布"
                )
                st.plotly_chart(fig, use_container_width=True)

        # 项目列表
        st.subheader("📋 GitLab项目列表")
        display_columns = ['name', 'description', 'visibility', 'star_count', 'forks_count', 'last_activity_at']
        available_columns = [col for col in display_columns if col in df.columns]

        if available_columns:
            st.dataframe(
                df[available_columns].head(20),
                use_container_width=True,
                hide_index=True
            )

    def display_commits_analysis(self, df: pd.DataFrame, repo_name: str):
        """显示GitLab提交分析"""
        if df.empty:
            st.warning("没有GitLab提交数据可显示")
            return

        st.subheader(f"📈 GitLab {repo_name} 提交分析")

        # 调试信息：显示原始数据结构
        with st.expander("🔍 调试信息 - 原始数据结构", expanded=False):
            st.write("**DataFrame列信息:**")
            st.json({
                "columns": list(df.columns),
                "shape": df.shape,
                "dtypes": {col: str(dtype) for col, dtype in df.dtypes.items()}
            })

            if len(df) > 0:
                st.write("**前3条记录样本:**")
                sample_data = df.head(3).to_dict('records')
                st.json(sample_data)

                st.write("**作者字段统计:**")
                author_stats = {
                    "unique_author_names": df['author_name'].nunique() if 'author_name' in df.columns else 0,
                    "empty_author_names": (df['author_name'] == '').sum() if 'author_name' in df.columns else 0,
                    "null_author_names": df['author_name'].isnull().sum() if 'author_name' in df.columns else 0,
                    "sample_author_names": df['author_name'].dropna().unique()[
                                           :10].tolist() if 'author_name' in df.columns else []
                }
                st.json(author_stats)

        # 基本统计
        col1, col2, col3, col4 = st.columns(4)

        with col1:
            st.metric("总提交数", len(df))

        with col2:
            unique_authors = df['author_name'].nunique() if 'author_name' in df.columns else 0
            st.metric("贡献者数量", unique_authors)

        with col3:
            if 'author_date' in df.columns:
                date_range = (df['author_date'].max() - df['author_date'].min()).days
                st.metric("时间跨度(天)", date_range)
            else:
                st.metric("时间跨度(天)", "N/A")

        with col4:
            total_changes = df['total_changes'].sum() if 'total_changes' in df.columns else 0
            st.metric("总代码变更", f"{total_changes:,}")

        # 创建图表
        self._create_commit_charts(df)

    def _create_commit_charts(self, df: pd.DataFrame):
        """创建GitLab提交分析图表"""
        if df.empty:
            return

        # 1. 贡献者统计
        if 'author_name' in df.columns:
            st.subheader("👥 Top GitLab贡献者")
            top_contributors = df['author_name'].value_counts().head(10)

            fig = px.bar(
                x=top_contributors.values,
                y=top_contributors.index,
                orientation='h',
                title="Top 10 GitLab贡献者提交统计",
                labels={'x': '提交次数', 'y': '贡献者'}
            )
            fig.update_layout(height=400)
            st.plotly_chart(fig, use_container_width=True)

        # 2. 时间分布分析
        if 'author_date' in df.columns:
            col1, col2 = st.columns(2)

            with col1:
                # 每小时提交分布
                if 'hour' in df.columns:
                    st.subheader("🕐 每小时提交分布")
                    hourly_commits = df['hour'].value_counts().sort_index()

                    fig = px.line(
                        x=hourly_commits.index,
                        y=hourly_commits.values,
                        title="每小时提交分布",
                        labels={'x': '小时', 'y': '提交次数'}
                    )
                    fig.update_traces(mode='lines+markers')
                    st.plotly_chart(fig, use_container_width=True)

            with col2:
                # 每周提交分布
                if 'weekday' in df.columns:
                    st.subheader("📅 每周提交分布")
                    weekday_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
                    weekday_commits = df['weekday'].value_counts().reindex(weekday_order, fill_value=0)

                    fig = px.bar(
                        x=weekday_order,
                        y=weekday_commits.values,
                        title="每周提交分布",
                        labels={'x': '星期', 'y': '提交次数'}
                    )
                    st.plotly_chart(fig, use_container_width=True)

        # 3. 月度趋势
        if 'author_date' in df.columns:
            st.subheader("📈 月度提交趋势")
            monthly_commits = df.groupby(df['author_date'].dt.to_period('M')).size()

            if not monthly_commits.empty:
                fig = px.line(
                    x=[str(period) for period in monthly_commits.index],
                    y=monthly_commits.values,
                    title="月度提交趋势",
                    labels={'x': '月份', 'y': '提交次数'}
                )
                fig.update_traces(mode='lines+markers')
                st.plotly_chart(fig, use_container_width=True)

        # 4. 代码变更分析
        if 'total_changes' in df.columns and 'author_name' in df.columns:
            st.subheader("💻 代码变更分析")
            author_changes = df.groupby('author_name')['total_changes'].sum().sort_values(ascending=False).head(10)

            if not author_changes.empty:
                fig = px.bar(
                    x=author_changes.index,
                    y=author_changes.values,
                    title="Top 10 GitLab贡献者代码变更量",
                    labels={'x': '贡献者', 'y': '代码变更行数'}
                )
                fig.update_layout(xaxis_tickangle=-45)
                st.plotly_chart(fig, use_container_width=True)

    def validate_config(self, access_token: str, gitlab_url: str) -> bool:
        """验证GitLab配置"""
        if not access_token:
            st.error("请填写GitLab Access Token")
            return False
        if not gitlab_url:
            st.error("请填写GitLab URL")
            return False
        return True
